/******************************************************************************
//             INTEL CORPORATION PROPRIETARY INFORMATION
//  This software is supplied under the terms of a license agreement or
//  nondisclosure agreement with Intel Corporation and may not be copied
//  or disclosed except in accordance with the terms of that agreement.
//    Copyright(c) 2000 - 2001 Intel Corporation. All Rights Reserved.
//
//  VSS: 
//     $Workfile: $
//     $Revision: $
//     $Date:     $
//     $Archive:  $
//
//  Description:
//      Intel(R) Integrated Performance Primitives - JPEG Helper file.
//      This file contains statistic functions to collect FREG of 
//      occurrrence of symbol V (Progressive)
//
//  History:
//     Date         Author        Changes
//     2001/2/1     Jerry Hu      Created (Version 0.2, K1, k4 in T.81)
//
********************************************************************************/
#include "_ippjpeg.h"
#include "ijehufsh.h"

/******************************************************************************
// Name:             ippiGetHuffmanFREQ_JPEG_DCFirst_16s
// Description:      Collect frequency of DC coefficient for the first scan.
// Input Arguments: 
//             pSrc: Identifies source coefficient data in 8x8.
//          pDCPred: Identifies the previous DC value of prediction.
//              al:  Indiactes successive approximation bit position low (for point tranform)
//
// Output Arguments:
//          pDstACFREQ: Identifies frequency for AC coefficient. Its length shall be 258.
//          pDCPred: Identifies the current DC value of prediction.
//
// Remarks:      
//                   1. The start address of "pSrc" shall be aligned at 4byte boundary.
//                   2. It is better to do this alignement at 32byte boundary to optimize 
//                      D-Cache accessing.
//                   3. *pDCPred shall be 0 in initial or after each restart interval.
//
// Returns:         
//    IPP_STATUS_OK: Succeeds.
******************************************************************************/
IPPFUN(IppStatus, ippiGetHuffmanFREQ_JPEG_DCFirst_16s) (const Ipp16s *pSrc, 
                                                        int          *pDstDCFREQ,
                                                        Ipp16s       *pDCPred,
                                                        int          al)
                             
{
    int    data;
    int    ssss;
    Ipp16s value;

    _IPP_CHECK_ARG((NULL!=pSrc)&&(NULL!=pDstDCFREQ));
    _IPP_CHECK_ARG(NULL!=pDCPred);
    _IPP_CHECK_ARG(0<=al);
    /*
    // Encode DC Coefficient
    */
    value = (Ipp16s)(pSrc[0]>>al);
    data  = value - *pDCPred;
    *pDCPred = value;

    _CSIZE(ssss, data);
    
    pDstDCFREQ[ssss]++;

    return IPP_STATUS_OK;
} 

/******************************************************************************
// Name:             ippiGetHuffmanFREQ_JPEG_ACFirst_16s
// Description:      Collect frequency of AC coefficient for the first scan.
// Input Arguments: 
//             pSrc: Identifies source coefficient data in 8x8.
//          pEOBRun: Identifies EOB run length in last time.
//               ss: Indicates start of selection.
//               se: Indicates end of selection.
//               al: Indiactes successive approximation bit position low (for point tranform)
//
// Output Arguments:
//          pDstACFREQ: Identifies frequency for AC coefficient. Its length shall be 258.
//
// Remarks:      
//                   1. The start address of "pSrc" shall be aligned at 4byte boundary.
//                   2. It is better to do this alignement at 32byte boundary to optimize 
//                      D-Cache accessing.
//
// Returns:         
//    IPP_STATUS_OK: Succeeds.
******************************************************************************/
IPPFUN(IppStatus, ippiGetHuffmanFREQ_JPEG_ACFirst_16s) (const Ipp16s *pSrc,
                                                        int          *pDstACFREQ,
                                                        int          *pEOBRun,
                                                        int          ss,
                                                        int          se,
                                                        int          al)
                             
{
    int    rrrr;
    int    ssss;
    int    rs;
    int    data;
    int    k;

    _IPP_CHECK_ARG((NULL!=pSrc)&&(NULL!=pDstACFREQ));
    _IPP_CHECK_ARG((NULL!=pEOBRun)&&(0<=*pEOBRun));
    _IPP_CHECK_ARG((0<ss)&&(ss<=se)&&(64>se));

    /*
    // Encode AC Coefficient(s)
    */

    rrrr = 0;

    for (k=ss; k<=se; k++) {
        data = pSrc[_nIppIZigZagIndex[k]];
        if (0==data) {
           rrrr++; /* Increment run-length of zeroes */
           continue;
        } 
        /*
        // Point trandorm by al
        */
        if (0>data) {
            data=-data;
        } 
        data>>=al;

        if (0==data) {
           rrrr++; /* Increment run-length of zeroes */
           continue;
        } 

        if (0<(*pEOBRun)) {
            _EOBSIZE(ssss, (*pEOBRun));
            pDstACFREQ[ssss<<4]++;
            (*pEOBRun)=0;
        }

        // if run length > 15, must emit special run-length-16 codes (0xf0)
        while(rrrr > 15) {
            pDstACFREQ[0xf0]++;
            rrrr-=16;
        }
    
        /* Encode ZZ(K) */
        _CSIZE(ssss, data);
        rs=(rrrr<<4)+ssss;
        pDstACFREQ[rs]++;
        rrrr = 0;
    }
  
    if (rrrr>0) {
        (*pEOBRun)++;
        if (0x7fff==(*pEOBRun)) {
            _EOBSIZE(ssss, (*pEOBRun));
            pDstACFREQ[ssss<<4]++;
            (*pEOBRun)=0;
        }
    }

    return IPP_STATUS_OK;
} 

/******************************************************************************
// Name:             ippiGetHuffmanFREQ_JPEG_ACRefine_16s
// Description:      Collect frequency of AC coefficient for the first scan.
// Input Arguments: 
//             pSrc: Identifies source coefficient data in 8x8.
//      pDstBitsLen: Indicates the number of bits that have been Encoded before.
//          pEOBRun: Identifies EOB run length in last time.
//     pCoeffBuffer: Identifies coefficients buffer which size shall be larger than 256+31;
//           pBELen: Identifies BE length.
//               ss: Indicates start of selection.
//               se: Indicates end of selection.
//               al: Indiactes successive approximation bit position low (for point tranform)
//
// Output Arguments:
//          pDstACFREQ: Identifies frequency for AC coefficient. Its length shall be 258.
//
// Remarks:      
//                   1. The start address of "pSrc" and "pBitBuffer"shall be aligned at 4byte boundary.
//                   2. It is better to do this alignement at 32byte boundary to optimize 
//                      D-Cache accessing.
//
// Returns:         
//    IPP_STATUS_OK: Succeeds.
******************************************************************************/
IPPFUN(IppStatus, ippiGetHuffmanFREQ_JPEG_ACRefine_16s) (const Ipp16s *pSrc,
                                                         int          *pDstACFREQ,
                                                         int          *pEOBRun,
                                                         Ipp8u        *pCoeffBuf,
                                                         int          *pBELen,
                                                         int          ss,
                                                         int          se,
                                                         int          al)

{
    int    k;
    int    ssss, rrrr, rs;
    int    value;
    int    EOB;
    int    BE, BR;
    int    *pTempBuf;

    _IPP_CHECK_ARG((NULL!=pSrc)&&(NULL!=pDstACFREQ)&&(NULL!=pCoeffBuf));
    _IPP_CHECK_ARG((NULL!=pEOBRun)&&(0<=*pEOBRun));
    _IPP_CHECK_ARG((NULL!=pBELen)&&(0<=*pBELen));
    _IPP_CHECK_ARG(_IPP_CHECK_ALIGN_4BYTE(pSrc));
    _IPP_CHECK_ARG((0<ss)&&(ss<=se)&&(64>se));

    BR   = 0;
    BE   = *pBELen;
    EOB  = 0;
    rrrr = 0;

    pTempBuf  = (int *)_IPP_32BYTEALIGN(pCoeffBuf);
  
    /* 
    // 1. Find EOB 
    // 2. Apply point transform by al
    */
    for (k = ss; k <= se; k++) {
        value = pSrc[_nIppIZigZagIndex[k]];

        /* value is abs value of input */
        if (value < 0) {
           value = -value;
        }

        /* apply the point transform */
        value >>= al;
        pTempBuf[k] = value;

        /* EOB = index of last newly-nonzero coef */
        if (1==value) {
           EOB = k;
        }
    }

    /*
    // Encode the AC coefficients per section G.1.2.3, Figure G.7
    */
    for (k = ss; k <= se; k++) {
        value = pTempBuf[k];

        if (value == 0) {
           rrrr++;
           continue;
        }

        /* 
        // Process Zero run 
        // Figure G.7 in T.81 cause a error, 
        // k should be greater than EOB
        */
        while ((rrrr>15)&&(EOB>=k)) {
            if (0<(*pEOBRun)) {
                _EOBSIZE(ssss, (*pEOBRun));
                pDstACFREQ[ssss<<4]++;
                (*pEOBRun)=0;
            }

            if (0<BE) {
                /* append BE bits */
                BE=0;
            }            
          
            /* Encode ZRL */
            pDstACFREQ[0xf0]++;
            rrrr-=16;

            if (0<BR) {
                /* append BE bits */
                BR=0;
            }
        }

        if (1<value) {
           /* Append correction bit */
           BR++;
           continue;
        }

        /*
        // Processing zero history value
        */
        if (0<(*pEOBRun)) {
            _EOBSIZE(ssss, (*pEOBRun));
            pDstACFREQ[ssss<<4]++;
            (*pEOBRun)=0;
        }

        if (0<BE) {
            /* append BE bits */
            BE=0;
        }            
          
        /* Encoding zero history value according to rule a */
        rs    = (rrrr<<4)+1;
        pDstACFREQ[rs]++;

        if (0<BR) {
            /* append BE bits */
            BR=0;
        }
        
        /* reset ZRL */
        rrrr=0;
    }

    if ((0<rrrr)||(0<BR)) {
        (*pEOBRun)++;
        BE += BR;
        /*
        // Buffer length for the buffered bits is 1024
        // EOBRun is used to process the overflow for the buffer
        */
        if ((0x7FFF==(*pEOBRun))||(BE>(_MAXCORRBITS-63))) {
            if (0<(*pEOBRun)) {
                _EOBSIZE(ssss, (*pEOBRun));
                pDstACFREQ[ssss<<4]++;
                (*pEOBRun)=0;
            }
            if (0<BE) {
                /* append BE bits */
                BE=0;
            }            
        }
    }

    *pBELen=BE;

    return IPP_STATUS_OK;
}

/******************************************************************************
// Name:             ippiGetHuffmanFREQ_JPEG_ACFinal
// Description:      Encods AC coefficients for the first scan.
// Input Arguments: 
//        srcEOBRun: Indicates EOB run length.
//          pDstACFREQ: Identifies frequency for AC coefficient. Its length shall be 258.
//
// Output Arguments:
//
// Remarks:          None.
//
// Returns:         
//    IPP_STATUS_OK: Succeeds.
******************************************************************************/
IPPFUN(IppStatus, ippiGetHuffmanFREQ_JPEG_ACFinal)(int srcEOBRun,
                                                   int *pDstACFREQ)
{

    int ssss;

    _IPP_CHECK_ARG(0<=srcEOBRun);
    _IPP_CHECK_ARG(NULL!=pDstACFREQ);

    if (0<srcEOBRun) {
        _EOBSIZE(ssss, srcEOBRun);
        pDstACFREQ[ssss<<4]++;
    }
    return IPP_STATUS_OK;
}


/* EOF */
